package com.coder4j.auth.service;

import com.coder4j.auth.entity.AuthResourceEntity;
import com.coder4j.auth.mapper.AuthResourceMapper;
import com.coder4j.auth.vo.*;
import com.coder4j.cache.ApiCache;
import com.coder4j.cache.ButtonCache;
import com.coder4j.cache.GroupCache;
import com.coder4j.cache.RoleCache;
import com.coder4j.starter.mybatis.BasePage;
import com.coder4j.starter.tools.enums.SeparatorEnums;
import com.coder4j.starter.tools.util.ListUtils;
import com.coder4j.starter.tools.util.StringUtils;
import com.coder4j.starter.tools.vo.BaseException;
import com.coder4j.starter.web.BaseServiceImpl;
import com.coder4j.starter.web.util.AuthUtils;
import com.coder4j.starter.web.jwt.AuthVO;
import org.springframework.stereotype.Service;
import org.springframework.beans.BeanUtils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 资源
 * @author keller
 * @date 2024-05-07 18:10:11
 */
@Service
@Slf4j
public class AuthResourceService extends BaseServiceImpl<AuthResourceMapper,AuthResourceEntity,AuthResourceVO>  {

    @Resource
    private AuthResourceMapper mapper;

    @Override
    public AuthResourceVO entity2Vo(AuthResourceEntity entity) {
        AuthResourceVO vo = new AuthResourceVO();
        BeanUtils.copyProperties(entity,vo);
        vo.setGroupName(GroupCache.getGroupName(vo.getGroupId()));
        return vo;
    }

    @Override
    public AuthResourceEntity vo2Entity(AuthResourceVO vo) {
        AuthResourceEntity entity = new AuthResourceEntity();
        BeanUtils.copyProperties(vo, entity);
        return entity;
    }

    @Transactional
    public void initMenuAndButton(List<MenuVO> list) {
        mapper.deleteAll();

        for (MenuVO vo : list) {
            //添加菜单
            AuthResourceEntity entity = AuthResourceEntity.initMenu(vo.getName(),vo.getWebPath());
            this.baseSave(entity);

            if(ListUtils.isEmpty(vo.getButtonList())){
                continue;
            }
            //添加按钮
            List<AuthResourceEntity> buttonList = new ArrayList<>();
            for (ButtonVO buttonVO : vo.getButtonList()) {
                AuthResourceEntity button = AuthResourceEntity.initButton(entity.getId(),buttonVO.getName(),buttonVO.getUniqueKey());
                buttonList.add(button);
            }
            this.baseSaveList(buttonList);
        }
    }

    public BasePage<MenuVO> list(AuthResourceQuery query) {
        BasePage<AuthResourceEntity> page = this.baseQueryPage(query);
        BasePage<MenuVO> menuPage = new BasePage<>();
        BeanUtils.copyProperties(page, menuPage);

        List<MenuVO> list = new ArrayList<>();
        if(ListUtils.isEmpty(page.getDataList())){
            return menuPage;
        }

        for (AuthResourceEntity entity : page.getDataList()) {
            MenuVO menuVO = new MenuVO();
            menuVO.setId(entity.getId());
            menuVO.setName(entity.getName());
            menuVO.setGroupId(entity.getGroupId());
            menuVO.setGroupName(GroupCache.getGroupName(entity.getGroupId()));
            menuVO.setWebPath(entity.getWebPath());
            menuVO.setSort(entity.getSort());
            menuVO.setIconName(entity.getIconName());
            menuVO.setApiSignatureCode(entity.getApiSignatureCode());

            //如果菜单绑定了API,取出API名称
            if(StringUtils.notEmpty(entity.getApiSignatureCode())){
                List<String> apiNames = new ArrayList<>();
                for (String code : entity.getApiSignatureCode().split(",")) {
                    apiNames.add(ApiCache.getApiName(code));
                }
                menuVO.setApiNames(apiNames);
            }

            //取出菜单关联的按钮
            menuVO.setButtonList(ButtonCache.getButtonList(entity.getId()));

            list.add(menuVO);
        }

        menuPage.setDataList(list);
        return menuPage;
    }

    public List<MenuTreeVO> tree() {
        List<MenuVO> list = mapper.queryMenuList();
        if(ListUtils.isEmpty(list)){
            return new ArrayList<>();
        }

        for (MenuVO vo : list) {
//            //为菜单装填按钮
//            if(vo.getGroupParentId() == null){
//                vo.setGroupParentId(GlobalConfig.RootId);
//            }
            //如果未分组，分组ID设置为 -1
            if(vo.getGroupId() == null){
                vo.setGroupId(-1L);
                vo.setGroupName("未分组");
            }
        }

        //将排好序的分组ID取出来
        List<Long> groupIds = list.stream().map(MenuVO::getGroupId).collect(Collectors.toList());
        //按照菜单组分组
        Map<Long, List<MenuVO>> map = list.stream().collect(Collectors.groupingBy(MenuVO::getGroupId));

        List<MenuTreeVO> voList = new ArrayList<>();
        //按顺序获取分组菜单
        for (Long groupId : groupIds) {
            if(!map.containsKey(groupId)){
                continue;
            }
            List<MenuVO> menuVOList = map.get(groupId);
            map.remove(groupId);
            //构建菜单组
            MenuTreeVO group = new MenuTreeVO();
            group.setId(groupId);
            List<MenuTreeVO.Menu> menuList = new ArrayList<>();
            for (MenuVO vo : menuVOList) {
                group.setParentId(vo.getGroupParentId());
                group.setGroupName(vo.getGroupName());

                MenuTreeVO.Menu menu = new MenuTreeVO.Menu();
                menu.setMenuId(vo.getId());
                menu.setMenuName(vo.getName());
                menu.setMenuPath(vo.getWebPath());
                menu.setMenuGroupName(vo.getGroupName());
                menu.setButtonList(ButtonCache.getButtonList(vo.getId()));

                menuList.add(menu);
            }
            group.setMenuList(menuList);
            voList.add(group);
        }

          return voList;

//        MenuTreeVO root = new MenuTreeVO();
//        root.setId(GlobalConfig.RootId);
//        this.baseInitChildren(root,voList);
//        return root.getChildren();
    }

    public List<String> queryApis(List<Long> ids) {
        if(ListUtils.isEmpty(ids)){
            return null;
        }
        List<AuthResourceEntity> list = this.baseGetListByIds(ids);
        List<String> apis = new ArrayList<>();
        for (AuthResourceEntity item : list) {
            if(StringUtils.notEmpty(item.getApiSignatureCode())){
                apis.addAll(Arrays.asList(item.getApiSignatureCode().split(SeparatorEnums.Comma.value)));
            }
        }
        return apis;
    }

    public List<UserMenuVO> userMenu() {
        AuthVO authVO = AuthUtils.getAuthVO();
        if(authVO == null){
            throw BaseException.noAuth();
        }

        Long roleId = authVO.getRoleId();
        if(roleId == null){
            throw BaseException.noAuth();
        }
        List<UserMenuVO> voList = new ArrayList<>();

        //查询所有菜单
        List<MenuVO> list = mapper.queryMenuList();
        if(ListUtils.isEmpty(list)){
            return voList;
        }
        //查询角色对应的权限
        List<Long> rights = RoleCache.getRights(roleId);

        log.error("--==NND==--00--{},{}",rights==null?0:rights.size(),roleId);

        //过滤出角色拥有的菜单
        list = list.stream().filter(item -> rights.contains(item.getId())).collect(Collectors.toList());
        if(ListUtils.isEmpty(list)){
            return voList;
        }

        for (MenuVO vo : list) {
            //如果未分组，分组ID设置为 -1
            if(vo.getGroupId() == null){
                vo.setGroupId(-1L);
                vo.setGroupName("未分组");
            }
        }

        //将排好序的分组ID取出来
        List<Long> groupIds = list.stream().map(MenuVO::getGroupId).collect(Collectors.toList());
        //按照菜单组分组
        Map<Long, List<MenuVO>> map = list.stream().collect(Collectors.groupingBy(MenuVO::getGroupId));

        //按顺序获取分组菜单
        for (Long groupId : groupIds) {
            if(!map.containsKey(groupId)){
                continue;
            }
            List<MenuVO> menuVOList = map.get(groupId);
            map.remove(groupId);
            //构建菜单组
            UserMenuVO group = new UserMenuVO();
            group.setKey(groupId + "");

            List<UserMenuVO> menuList = new ArrayList<>();
            for (MenuVO vo : menuVOList) {
                group.setLabel(vo.getGroupName());
                group.setIconName(vo.getGroupIcon());
                UserMenuVO menu = new UserMenuVO();
                menu.setTitle(vo.getGroupName());
                menu.setKey(vo.getWebPath());
                menu.setLabel(vo.getName());
                menu.setIconName(vo.getIconName());
                menuList.add(menu);
            }
            group.setChildren(menuList);
            voList.add(group);
        }

        return voList;

    }
}
